﻿#include "WindowMain.h"

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

WindowMain::WindowMain(HINSTANCE hInstance, int nCmdShow, int x, int y, int width, int height)
{
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_PROJECT01, szWindowClass, MAX_LOADSTRING);

    dwStyle = WS_CAPTION | WS_SYSMENU;

    this->width = width;
    this->height = height;
    this->hInstance = hInstance;

    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(wcex);// WNDCLASSEXW结构体大小

    wcex.style = CS_HREDRAW | CS_VREDRAW;// 如果窗口大小改变了重新绘制窗口
    wcex.lpfnWndProc = HandleMsgSetup;// 窗口消息处理函数
    wcex.cbClsExtra = 0;// 无附加窗口类内存
    wcex.cbWndExtra = 0;// 无附加窗口内存
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROJECT01));// 图标
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);// 鼠标指针
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);// 背景画刷
    wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PROJECT01);// 菜单资源
    wcex.lpszClassName = szWindowClass;// 窗口类名
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));// 小图标

    RegisterClassEx(&wcex);

    RECT rect;
    rect.left = rect.top = 0;
    rect.right = width;
    rect.bottom = height;
    AdjustWindowRect(&rect, dwStyle, TRUE);//根据所需的客户端矩形大小计算窗口矩形的所需大小

    hWnd = CreateWindow(
        szWindowClass, // 窗口类名
        szTitle, // 窗口名，标题名
        dwStyle,// 窗口样式
        x,//显示窗口位置
        y,
        rect.right - rect.left,//创建窗口大小
        rect.bottom - rect.top,
        nullptr, // 无父窗口
        nullptr,// 菜单
        hInstance, //应用程序实例
        this
    );
    
    if (!hWnd)
    {
        throw std::runtime_error("CreateWindowW error");
    }

    // 创建控件
    pTreeView = std::make_unique<TreeView>(hInstance, hWnd, "树视图");
    pListView = std::make_unique<ListView>(hInstance, hWnd, "列表视图");
    pEditView = std::make_unique<EditView>(hInstance, hWnd, "编辑视图");
    
    // 获取客户端窗口大小
    GetClientRect(hWnd, &rect);

    // 设置子控件在窗口的位置
    pTreeView->SetPos(
        0, 0,
        int(rect.right * 0.3), rect.bottom);
    pListView->SetPos(
        int(rect.right * 0.3), int(rect.bottom * 0.7),
        int(rect.right * 0.7), int(rect.bottom * 0.3));
    pEditView->SetPos(
        int(rect.right * 0.3), rect.top,
        int(rect.right * 0.7), int(rect.bottom * 0.7));

    // 初始化
    pTreeView->Init();
    pListView->Init();

    //任养面上业不的汉本
    LPCSTR lpszlatin = "Lorem ipsum dolor sit amet, consectetur"
        "adipisicing elit,sed do eiusmod tempor "
        "incididunt ut labore et dolore magna "
        "aliqua. Ut enim ad minim veniam, quis "
        "nostrud exercitation ullamco laboris nisi "
        "ut aliguipexea commodo consequat.Duis"
        "aute irure dolor in reprehenderit in "
        "voluptatevelitesse cillum dolore eu"
        "fugiat nulla pariatur. Excepteur sint"
        "occaecat cupidatat non proident,sunt"
        "in culpa qui officia deserunt mollit"
        "anim id est laborum.";
    pEditView->ShowTextOnEdit((LPSTR)lpszlatin);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    hWndAssit = nullptr;
}

WindowMain::~WindowMain()
{

}

LRESULT WindowMain::wm_create(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return 0;
}

LRESULT WindowMain::wm_rbuttondown(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HMENU hMenuPop;// 弹出菜单
    // 创建弹出菜单
    hMenuPop = CreatePopupMenu();
    // 添加菜单项
    AppendMenu(hMenuPop, MF_STRING, ID_EXIT, "退出");
    POINT pt;
    // 获取鼠标在屏幕的坐标
    GetCursorPos(&pt);
    // 将鼠标坐标转换成窗口坐标
    //ScreenToClient(hWnd, &pt);
    // 显示菜单
    TrackPopupMenu(hMenuPop, TPM_TOPALIGN | TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL);

    //释放菜单资源
    DestroyMenu(hMenuPop);
    return 0;
}

LRESULT WindowMain::wm_notify(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    LPNMHDR phdr = (LPNMHDR)lParam;
    switch (phdr->code)
    {
        //如果是右键单击，则调用nRclickTree函数，弹出右键菜单
    case NM_RCLICK:
        pTreeView->OnRclick(phdr);
        break;
    default:
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

LRESULT WindowMain::wm_command(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int wmId = LOWORD(wParam);
    // 分析菜单选择:
    switch (wmId)
    {
    case IDM_ABOUT:
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
        break;
    case IDM_EXIT:
        PostQuitMessage(0);
        break;
    case ID_EXIT:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

LRESULT WindowMain::wm_paint(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);
    // TODO: 在此处添加使用 hdc 的任何绘图代码...
    EndPaint(hWnd, &ps);

    return 0;
}

LRESULT WindowMain::wm_activate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (wParam == WA_ACTIVE || wParam == TRUE)
    {
        // 窗口被激活，可以在这里执行相关操作
        //MessageBox(hWnd, TEXT("窗口被激活！"), TEXT("提示"), MB_OK);
        OutputDebugString("窗口被激活\n");
    }
    else if (wParam == WA_INACTIVE || wParam == FALSE)
    {
        // 窗口失活，可以在这里执行相关操作
        // MessageBox(hWnd, TEXT("窗口失活！"), TEXT("提示"), MB_OK);
        OutputDebugString("窗口失活\n");
    }
    return 0;
}

LRESULT WindowMain::wm_setfocus(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (nullptr != hWndAssit && IsWindowVisible(hWndAssit))
    {
        OutputDebugString("wm_setfocus\n");
        //ShowWindow(hWndAssit, SW_SHOW);
        //SetWindowPos(hWndAssit, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}

LRESULT WindowMain::wm_destroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PostQuitMessage(0);
    return 0;
}

void WindowMain::SethWndAssit(HWND hWndAssit)
{
    this->hWndAssit = hWndAssit;
}

LRESULT CALLBACK WindowMain::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // 使用从CreateWindow() 传入的create参数在WinAPI端存储窗口类指针
    if (msg == WM_NCCREATE)
    {
        // 从创建数据中提取窗口类的ptr
        CREATESTRUCTW* pCreate = (CREATESTRUCTW*)lParam;
        WindowMain* pWnd = (WindowMain*)pCreate->lpCreateParams;
        // 设置WinAPI托管的用户数据以将ptr存储到窗口实例
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pWnd);
        // 安装完成后，将消息进程设置为正常（非安装）处理程序
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&WindowMain::HandleMsgThunk);
        // 将消息转发给窗口实例处理程序
        return pWnd->WndProc(hWnd, msg, wParam, lParam);
    }
    // 如果我们在WM_NCCREATE消息之前收到一条消息，请使用默认处理程序进行处理
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

LRESULT CALLBACK WindowMain::HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // 将ptr检索到窗口实例
    WindowMain* pWnd = (WindowMain*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    // 将消息转发给窗口实例处理程序
    return pWnd->WndProc(hWnd, msg, wParam, lParam);
}

LRESULT CALLBACK WindowMain::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:     return wm_create(hWnd, msg, wParam, lParam);// 窗口创建时接受消息
    case WM_SIZE:       break;// 窗口大小改变时候收到消息
    case WM_NOTIFY:     return wm_notify(hWnd, msg, wParam, lParam);// 控件发送给父窗口
    case WM_RBUTTONDOWN:return wm_rbuttondown(hWnd, msg, wParam, lParam);// 鼠标右键按下
    case WM_COMMAND:    return wm_command(hWnd, msg, wParam, lParam);// 命令输入，菜单，按钮
    case WM_PAINT:      return wm_paint(hWnd, msg, wParam, lParam);// 窗口绘制时收到消息
    case WM_MOVING:     break;// 当窗口移动时
    case WM_ACTIVATE:   return wm_setfocus(hWnd, msg, wParam, lParam);
    case WM_SETFOCUS:   return wm_setfocus(hWnd, msg, wParam, lParam);// 窗口获得聚焦
    case WM_KILLFOCUS:  break;// 窗口失去聚焦
    case WM_DESTROY:    return wm_destroy(hWnd, msg, wParam, lParam);// 窗口销毁
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

